package summarizer;

import java.util.ArrayList;
import java.util.GregorianCalendar;
import java.util.HashMap;

import summarizer.newversion.Summarizer;
import thesis.DataUtil;
import thesis.FSModule;
import thesis.InfoUnit;
import thesis.DataObject;
import thesis.Summary;


public class InfoDrivenSummarizer extends Summarizer {

	private final double alpha;
	private final double beta;
	private final double gamma;
	private final double[][] probs;
	private final ArrayList<InfoUnit> infoUnits;
	private HashMap<Long, DataObject> memoryTweets = new HashMap<Long, DataObject>();
	private double currQual;
	private double currDiv;

	public InfoDrivenSummarizer(final double[][] probs,
			ArrayList<InfoUnit> infoUnits, double alpha, double beta,
			double gamma) {
		this.alpha = alpha;
		this.beta = beta;
		this.gamma = gamma;

		this.probs = probs;
		this.infoUnits = infoUnits;
	}

	private void preprocess(Summary summary, int K) {
		// initialized totalInfo contained in each tweet
		this.currQual = 0;
		this.currDiv = 1;
		// compute gain for each info unit
		double totalUnitsInO = 0;
		for (DataObject t : memoryTweets.values()) {
			for (InfoUnit unit : infoUnits) {
				totalUnitsInO += probs[t.getInternId()][unit.getInternId()]
						* unit.getWeight();
			}
		}
		for (InfoUnit unit : infoUnits) {
			double total = 0;
			for (DataObject t : memoryTweets.values()) {
				total += probs[t.getInternId()][unit.getInternId()]
						* unit.getWeight();
			}
			unit.setGain(total / totalUnitsInO);
			unit.setCovProb(0);
		}
	}

	private void greedProcess(int K, int numberOfPages, Summary summary) {
		while (summary.size() < K) {
			for (DataObject t : this.memoryTweets.values()) {
				t.setQual(currQual + t.getQuality() / K);
				double minDiv = currDiv;
				for (DataObject ts : summary.getMemoryTweets()) {
					double dist = DataUtil.dist(t, ts);
					if (dist < minDiv) {
						minDiv = dist;
					}
				}
				t.setDiv(minDiv);
				double totalCov = 0;
				for (InfoUnit unit : infoUnits) {
					double covP = 1 - (1 - unit.getCovProb())
							* (1 - probs[t.getInternId()][unit.getInternId()]);
					totalCov += covP * unit.getGain();
				}
				t.setCov(totalCov);
			}
			double bestScore = -1;
			DataObject bestT = null;
			for (DataObject t : this.memoryTweets.values()) {
				double score = alpha * t.getQual() + beta * t.getDiv() + gamma
						* t.getCov();
				if (score > bestScore) {
					bestScore = score;
					bestT = t;
				}
			}
			summary.addMemoryTweet(bestT);
			this.memoryTweets.remove(bestT.getDbId());
			// compute coverage of each information unit by current summary
			for (InfoUnit info : this.infoUnits) {
				info.setCovProb(1 - (1 - info.getCovProb())
						* (1 - probs[bestT.getInternId()][info.getInternId()]));
			}
			currQual = bestT.getQual();
			currDiv = bestT.getDiv();
			// System.out.println("Summary size: " + summary.size());
			// System.out.println("Quality: " + bestT.getQual() + " Diversity: "
			// + bestT.getDiv() + " Coverage: " + bestT.getCov());

		}
	}

	@Override
	public Summary computeSummary(int summaryDimension, int numberOfPages,
			HashMap<Long, DataObject> tweets, int dimSize) {
		this.memoryTweets = tweets;
		Summary summary = new Summary();
		if (summaryDimension <= 0 || this.memoryTweets.isEmpty()) {
			return summary;
		}
		executionTime = (new GregorianCalendar()).getTimeInMillis();
		preprocess(summary, summaryDimension);
		greedProcess(summaryDimension, numberOfPages, summary);
		executionTime = (new GregorianCalendar()).getTimeInMillis()
				- executionTime;
		return summary;
	}

	public String toString() {
		return "InfoDrivenSummaizer";
	}

	@Override
	public long getExecutionTime() {
		// TODO Auto-generated method stub
		return executionTime;
	}

}
